/*  Copyright 2003  Auri Marcelo Rizzo Vicenzi, Marcio Eduardo Delamaro, 			    Jose Carlos Maldonado

    This file is part of Jabuti.

    Jabuti is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as 
    published by the Free Software Foundation, either version 3 of the      
    License, or (at your option) any later version.

    Jabuti is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Jabuti.  If not, see <http://www.gnu.org/licenses/>.
*/


package br.jabuti.cmdtool;



import java.io.*;
import java.util.*;

import br.jabuti.project.TestSet;

import br.jabuti.project.*;

import br.jabuti.util.*;


/**

 This application program reports the coverage and the covered elements
 for each test case and each method w.r.t. all criterion.

 @version: 0.00001
 @author: Auri Marcelo Rizzo Vincenzi

*/
public class CoverageSummary {
    public static void usage() {
        System.out.println(ToolConstants.toolName + " v. " + ToolConstants.toolVersion);
        System.out.println("\nPrintCoverageSummary usage:");
        System.out.println("-------------------\n");
        System.out.println("java cmdtool.PrintCoverageSummary -p <project_file> [-all] [-pr] [-cl] [-me] [-ts] [-tc] [-f x -t y] [-x \"<number_list>\"]\n");
        System.out.println("      -p <project_file>       Specify the name of the Project to be used. The");
        System.out.println("                              Project must be a valid Project file (.jba) generated by");
        System.out.println("                              instrument the base class.");

        System.out.println("      -all                    Geraneta a complete summary report, including");
        System.out.println("                              information from project to method level, and the");
        System.out.println("                              test set and test case coverages.");

        System.out.println("      -pr                     Coverage summary by project.");
        
        System.out.println("      -cl                     Coverage summary by class.");
        
        System.out.println("      -me                     Coverage summary by method.");
        
        System.out.println("      -ts                     Coverage summary by test set.");        
        
        System.out.println("      -tc                     Coverage summary by test case.");
        
        System.out.println("      -f x                    Defines the number x of the first");                        
        System.out.println("                              test case to be considered.");
        System.out.println("                              Test cases whose numbers are lower than x");        
        System.out.println("                              will be disabled when computing the coverage.");                
        
        System.out.println("      -t y                    Defines the number y of the last");                        
        System.out.println("                              test case to be considered.");
        System.out.println("                              Test cases whose numbers are greater than y");        
        System.out.println("                              will be disabled when computing the coverage.");                
        
        System.out.println("      -x \"<number_list>\"    Defines a set of test case numbers that will");  
        System.out.println("                              be enabled when computing the coverage.");                
		System.out.println("                              By default all test cases are used");
		System.out.println("                              when computing the coverage.");                
        System.out.println("\nCopyright (c) 2002\n");
    }

    public static void main(String args[]) throws Throwable {
        String projectName = null;
        JabutiProject project = null;
        
        boolean isPr=false;
        boolean isCl=false;
        boolean isMe=false;
        boolean isTs=false;
        boolean isTc=false;
        int f=-1;
        int t=-1;
        String x = null;

        if (args.length > 0) {

            int i = 0;
			
            while ((i < args.length) && (args[i].startsWith("-"))) {
            	// Recovering the project
				if (("-p".equals(args[i])) && (i < args.length - 1)) {
                    i++;
                    projectName = args[i];
                } // Complete summary
                else if ("-all".equals(args[i])) {
                	isPr=isCl=isMe=isTs=isTc=true;
                } // Project summary
                else if ("-pr".equals(args[i])) {
                	isPr=true;
                } // Class summary
                else if ("-cl".equals(args[i])) {
                	isCl=true;
                } // Method summary
                else if ("-me".equals(args[i])) {
                	isMe=true;
                } // Test set summary
                else if ("-ts".equals(args[i])) {
                	isTs=true;
                } // Test case summary
                else if ("-tc".equals(args[i])) {
                	isTc=true;
                } // First test case number
                else if ("-f".equals(args[i])) {
                	i++;
                	try {
                		f = Integer.parseInt( args[i] );
                	} catch( NumberFormatException nfe ) {
                		System.err.println( "Option " + args[i-1] + ": invalid number " + args[i] );
						System.out.println("try java cmdtool.CoverageSummary -h for help.");
                		System.exit(1);
                	}
                } // Last test case number
                else if ("-t".equals(args[i])) {
                	i++;
                	try {
                		t = Integer.parseInt( args[i] );
                	} catch( NumberFormatException nfe ) {
                		System.err.println( "Option " + args[i-1] + ": invalid number " + args[i] );
						System.out.println("try java cmdtool.CoverageSummary -h for help.");
                		System.exit(1);
                	}
                } // Test case list
                else if ("-x".equals(args[i])) {
                	i++;
                	x = args[i];
                } else {
                    System.out.println("Error: Unrecognized option: " + args[i]);
                    System.out.println("try java cmdtool.CoverageSummary -h for help.");
                    System.exit(0);
                }
                i++;
            }

            // Checking if all essential parameters are not null
            if (projectName == null) {
                System.out.println("Error: Missing parameter!!!");
                usage();
                System.exit(1);
            }
			
            try {
                File theFile = new File(projectName);

                if (!theFile.isFile()) // verifica se existe
                {
                    System.out.println("File " + theFile.getName() + " not found");
                    System.exit(0);
                }
	          	
                project = JabutiProject.reloadProj( theFile.toString(), true );

                // Loading the test set file
				int ult = TestSet.getNumberOfTestCases();
				
				Vector v = null;
				// Check if there are test cases to be used
				if ( ult > 0 ) {
					if ( f > ult || t > ult ) {
	                    System.out.println("Invalid values for -f or -t.");						
	                    System.out.println("The maximum number of test cases is: " + ult);
    	                System.exit(1);
					}
					// Enabling the correct set of test cases
					if( f != -1 ) {
						if ( t != -1 ) {
							if ( f <= t ) {
								v = new Vector();
								for( int j = f; j <= t; j++ ) {
									v.add( new Integer( j ) );
								}
							} else {
			                    System.out.println("-f value should be lower than or equal -t value.");
		    	                System.exit(1);
							}
						} else {
		                    System.out.println("-t option requires a -f option");
	    	                System.exit(1);
						}
					}
					if ( x != null ) {
						if ( v == null ) {
							v = new Vector();
						}
						StringTokenizer st = new StringTokenizer( x );
						while (st.hasMoreTokens()) {
							int n = 0;
							try {
								 n = Integer.parseInt( st.nextToken() );
								 v.add( new Integer( n ) );
							} catch (NumberFormatException nfe ){
			               		System.err.println("Option -x: invalid number in the list." );
								System.out.println("Numbers should be provided separeted by a white space.");
								System.exit( 1 );
							}
						}
					}
						
					if ( v != null ) {
						// Desabling the complete test set							
						String[] labels = TestSet.getTestCaseLabels();
						for( int j = 0; j < labels.length; j++ ) {
							TestSet.desactivateTestCase( project, labels[j] );
						}
						// Enabling only the desired ones
						
						for( int j = 0; j < v.size(); j++ ) {
							Integer n = (Integer) v.elementAt( j );
							String label = ToolConstants.getFourDigitNumber( n.intValue() );	
							TestSet.activateTestCase( project, label );
						}
					}
				}
				
				// Refreshing the overall coverage
//				TestSet.updateOverallCoverage( project );

				// Saving the updated project
//				project.saveProject();
				
				if ( isPr ) {
					System.out.println( "Project Coverage" );
					System.out.println( project.coverage2TXT("") );
				}

				if ( isCl || isMe ) {
	                // For each class
	                String[] classFileNames = project.getAllClassFileNames();
	
	                for (i = 0; i < classFileNames.length; i++) {
	                    ClassFile cf = project.getClassFile(classFileNames[i]);
						if ( isCl ) {
							System.out.println( "Class Coverage: " + classFileNames[i] );
							System.out.println( cf.coverage2TXT("") );
						}
						
						if ( isMe ) {
		                    // For each method
		                    String[] methodsNames = cf.getAllMethodsNames();
		
							if ( methodsNames == null )
								continue;
								
		                    for (int j = 0; j < methodsNames.length; j++) {
		                        ClassMethod cm = cf.getMethod(methodsNames[j]);
								System.out.println( "Method Coverage: " + methodsNames[j] );
								System.out.println( cm.coverage2TXT("") );
							}
	                	}
	                }
				}
				
				if ( isTs || isTc ) {
	                
	                if ( isTs ) {
						System.out.println( "Test Set Coverage" );
						System.out.println( TestSet.coverage2TXT("") );
	                }
	                
	                if ( isTc ) {
		                // For each test case
		                String[] labels = TestSet.getTestCaseLabels();
		
	    	            for (i = 0; i < labels.length; i++) {
	        	            TestCase tc = TestSet.getTestCase( labels[i] );
						
							System.out.println( "Test Case Coverage: " + labels[i] );
							System.out.println( tc.coverage2TXT("") );
						}
	                }
				}
            } catch (Exception e) {
                ToolConstants.reportException(e, ToolConstants.STDERR );
                System.exit(0);
            }
        } else {
            usage();
        }
        System.exit(0);
    }
}
